package com.javafactroy.kunlong.bip.icp.message.data.netty.handler.client;

import com.javafactroy.kunlong.bip.icp.context.AppContext;
import com.javafactroy.kunlong.bip.icp.netty.client.framework.NettyClient;
import io.netty.channel.*;
import io.netty.util.concurrent.DefaultPromise;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
//import com.javafactroy.kunlong.icp.message.dxp.base.Message;
import com.javafactroy.kunlong.bip.icp.message.base.iface.IMessage;
import com.javafactroy.kunlong.bip.icp.netty.client.framework.DxpMsgSyncFutureMngr;

@Component
@ChannelHandler.Sharable // 标注一个channel handler可以被多个channel安全地共享
@Slf4j
@Data
@Scope("prototype")
public class NettyClientHandler extends SimpleChannelInboundHandler<Object> {
    String uuid;
    NettyClient nettyClient;
    DefaultPromise<IMessage> promise;

    /**
     * @param ctx
     * @param
     * @throws Exception
     * @Description: 服务端发生消息给客户端，会触发该方法进行接收消息
     * @Author: 雷建明
     * @Since: 2019年9月12日下午5:03:31
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {

        IMessage message = (IMessage) msg;
        log.info("客户端收到消息：{}", message);
        DxpMsgSyncFutureMngr.ackSyncMsg(message);
        if (promise != null) {
            promise.setSuccess(message);
            promise = null;
        }

    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("请求连接成功...");
        AppContext.appContext.getMapNettyClient().put(uuid, true);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

        super.channelInactive(ctx);
        AppContext.appContext.getMapNettyClient().remove(uuid);
        synchronized (nettyClient) {

            nettyClient.setIsConn(false);
        }
        log.info("连接被断开...{}", nettyClient.getIsConn());
//        // 使用过程中断线重连
//        final EventLoop eventLoop = ctx.channel().eventLoop();
//        eventLoop.submit(new Runnable() {
//            @Override
//            public void run() {
//                // 重连
//                //  nettyClient.start(nettyClient.getAppType());
//            }
//        });

    }

    /**
     * 处理异常, 一般将实现异常处理逻辑的Handler放在ChannelPipeline的最后
     * 这样确保所有入站消息都总是被处理，无论它们发生在什么位置，下面只是简单的关闭Channel并打印异常信息
     *
     * @param ctx
     * @param cause
     * @throws Exception
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();

        // 输出到日志中
        //ExceptionUtil.getStackTrace(cause);

        Channel channel = ctx.channel();
        if (channel.isActive()) {
            ctx.close();
        }
    }

}
